package 设计模式.原生模式;

import java.io.*;

/**
 * @description: 原生模式
 * 注意：浅拷贝，克隆出来的对象不是独立的，若属性中有引用对象，则为同一引用
 * 可以不耦合具体类的情况下克隆对象
 * 避免重复的初始化代码 即生成同样赋值属性的另一个实例对象
 * 更方便构造复杂对象
 * @author: Kk
 * @create: 2020-12-09 09:25
 **/
public class Prototype {
    public static void main(String[] args) throws CloneNotSupportedException {
        Component component=new Component("icon",1);
        Product product=new Product("产品1",1,component);

        Product clone = product.clone();
       /* System.out.println(product.component);
        System.out.println(clone.component);*/
        clone.getComponent().setIcon("change icon");
        System.out.println(product.component.getIcon());
        System.out.println(clone.component.getIcon());
    }
}

class Product implements Cloneable, Serializable {
    private static final long serialVersionUID=42L;
    String name;
    Integer part1;
    Component component;

    public Product(String name, Integer part1, Component component) {
        this.name = name;
        this.part1 = part1;
        this.component = component;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getPart1() {
        return part1;
    }

    public void setPart1(Integer part1) {
        this.part1 = part1;
    }

    public Component getComponent() {
        return component;
    }

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    protected Product clone() throws CloneNotSupportedException {
        //通过clone实现深拷贝
       /* Product clone = (Product) super.clone();
        Component clone1 = clone.getComponent().clone();
        clone.setComponent(clone1);
        return clone;*/

       //通过反序列化实现深拷贝
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
        try {
            ObjectOutputStream oos=new ObjectOutputStream(byteArrayOutputStream);
            oos.writeObject(this);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        try (ObjectInputStream ois=new ObjectInputStream(byteArrayInputStream)){
            Product clone = (Product)ois.readObject();
            return clone;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return this.hashCode()+"  Product{" +
                "name='" + name + '\'' +
                ", part1=" + part1 +
                ", component=" + component +
                '}';
    }
}

class Component implements Cloneable,Serializable{
    private static final long serialVersionUID=42L;
    String icon;
    Integer type;

    public Component(String icon, Integer type) {
        this.icon = icon;
        this.type = type;
    }

    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    @Override
    protected Component clone() throws CloneNotSupportedException {
        return (Component) super.clone();
    }

    @Override
    public String toString() {
        return this.hashCode()+"  Component{" +
                "icon='" + icon + '\'' +
                ", type=" + type +
                '}';
    }
}
